package tuvienna.jade.participant;

import jade.core.behaviours.WakerBehaviour;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import tuvienna.jade.InterestSet;
import tuvienna.jade.Tools;

/**
 * This is a participant who will just look at each table and memorizes
 * the amount of gained knowledge. Once done exploring, he will choose
 * the best fitting table and stay there.
 *
 */
public class ExploringParticipantAgent extends ParticipantAgent{

	private static final long serialVersionUID = -243421240631427835L;

	protected void setup() {
		super.setup();		

		addBehaviour(new WakerBehaviour(this, 3500) {
			private static final long serialVersionUID = 1345642262433L;
			protected void handleElapsedTimeout() {
				for (TableInformation table:tables.values()) {
					addBehaviour(new RequestTableSizeBehaviour(getAgent(), table));
				}
			}
		});
	
		addBehaviour(new WakerBehaviour(this, 4500) {
			private static final long serialVersionUID = 134561434262433L;
			protected void handleElapsedTimeout() {
				addBehaviour(new RegisterAtTableBehaviour(getAgent(), Tools.getRandom(tables.values()).getAID()));
				/*
				TableInformation biggestTable =  null;
				for (TableInformation table:tables.values()) {
					System.out.println(table.getAID().getLocalName()+":"+table.getSize());
					if (biggestTable == null || table.getSize() > biggestTable.getSize()) {
						biggestTable = table;
					}
				}
				if (biggestTable != null) {
					addBehaviour(new RegisterAtTableBehaviour(getAgent(), biggestTable.getAID()));
				}*/
			}
		});
	}
	
	
	protected void updateDiscussionTopic(InterestSet topic) {
		super.updateDiscussionTopic(topic);
		InterestSet relevantTopics = topic.filter(interests);
		//relevantTopics.print("EP");
		//topic.print("EP-Raw");
		//System.out.println("Gained("+getTable().getLocalName()+"): "+relevantTopics.sum().setScale(2,BigDecimal.ROUND_HALF_EVEN));
		
		TableInformation bestTable = getBestTable();
		
		// move to new table (if different)
		if (!bestTable.getAID().equals(table)) {
			addBehaviour(new DeregisterAtTableBehaviour(getAgent(), table,
					new RegisterAtTableBehaviour(getAgent(), bestTable.getAID())));
		}
	}

	/**
	 * This method tries to find the best table. In early phases, it tries
	 * to explore the tables, if information is complete, it will just return
	 * the one were the agent got the most knowledge.
	 */
	protected TableInformation getBestTable() {
		TableInformation bestTable = null;
		
		Collection<TableInformation> allTables = tables.values();
		Set<TableInformation> unexploredTables = new HashSet<TableInformation>();
		Set<TableInformation> exploredTables = new HashSet<TableInformation>();
		for (TableInformation table:allTables) {
			if (table.getSize() > 0) {
				if (table.getLastGainedKnowledgeTime() > -1) {
					exploredTables.add(table);
				} else {
					unexploredTables.add(table);
				}
			}
		}
		
		if (unexploredTables.size() > 0) { // explore tables
			bestTable =  unexploredTables.iterator().next();
		} else if (exploredTables.size() > 0){ // exploration done, choose best
			for (TableInformation table: exploredTables) {
				if (bestTable == null || bestTable.getLastGainedKnowledge().compareTo(
						table.getLastGainedKnowledge()) < 0) {
					bestTable = table;		
				}
			}
		} else if (allTables.size() > 0) { // all empty, just pick one
			bestTable = allTables.iterator().next();
		}
		
		return bestTable;
	}

}
